/**
 * File: 
 * Proj/Lab:
 * Author:
 * Date:
 * Section:
 * Email:
 */
package clientApp;

import java.util.ArrayList;

/**
 * @author Ben
 *
 */
public class DegreeAudit 
{


	
	public static boolean isComplete(Degree myDegree, ArrayList<CourseRecord> myCRs, Catalog myCatalog)
	{
		String[] mySections = myDegree.listSections();
		for(int i = 1; i <= mySections.length; i++)
		{
			Section presSec = myDegree.getSection(mySections[i]);
			if(examineSectionForCompletion(presSec, myCatalog, myCRs) == false)
			{
				return false;
			}
		}
		return true;
	}
	
	private static boolean examineSectionForCompletion(Section mySection, Catalog myCatalog, ArrayList<CourseRecord> myCRs)
	{
		Section.REQ_TYPE myType = mySection.getReqType();	
		int numSubsections = mySection.numSubsections();
		
		if(myType == Section.REQ_TYPE.Take_All)
		{
			for(int i = 1; i <= numSubsections; i++)
			{
				if(examineSubsectionForCompletion(i, mySection.getReqTypeBySubsection(i), mySection, myCatalog, myCRs) == false)
				{
					System.out.println(mySection.getReqTypeBySubsection(i));
					return false;
				}
			}
			return true;
		}
		else if(myType == Section.REQ_TYPE.Take_Any)
		{
			for(int i = 1; i <= numSubsections; i++)
			{
				if(examineSubsectionForCompletion(i, mySection.getReqTypeBySubsection(i), mySection, myCatalog, myCRs) == true)
				{
					return true;
				}
			}
			return false;
		}
		else if(myType == Section.REQ_TYPE.Take_X_Courses)
		{
			ArrayList<String> allCourseIDs = new ArrayList<String>();
			int x = mySection.getUnitsNeeded();
			for(int i = 1; i <= numSubsections; i++)
			{
				for(String[] series : mySection.getCoursesInSubsection(i))
				{
					ArrayList<String> courseIDs = examineSeriesForCompletion(series, myCRs);
					for(String id : courseIDs)
					{
						if(!allCourseIDs.contains(id))
						{
							allCourseIDs.add(id);
						}
					}
				}
			}
			if(x <= allCourseIDs.size())
			{
				return true;
			}
			return false;
		}
		else if(myType == Section.REQ_TYPE.Take_X_Creds)
		{
			ArrayList<String> allCourseIDs = new ArrayList<String>();
			int x = mySection.getUnitsNeeded();
			for(int i = 1; i <= numSubsections; i++)
			{
				for(String[] series : mySection.getCoursesInSubsection(i))
				{
					ArrayList<String> courseIDs = examineSeriesForCompletion(series, myCRs);
					for(String id : courseIDs)
					{
						if(!allCourseIDs.contains(id))
						{
							allCourseIDs.add(id);
						}
					}
				}
			}
			int credCount = 0;
			for(String id : allCourseIDs)
			{
				credCount += myCatalog.getCourse(id).getNumCreds();
			}
			if(x <= credCount)
			{
				return true;
			}
			return false;
		}
		else if(myType == Section.REQ_TYPE.XOR)
		{
			for(int i = 1; i <= numSubsections; i++)
			{
				if(examineSubsectionForCompletion(i, mySection.getReqTypeBySubsection(i), mySection, myCatalog, myCRs) == true)
				{
					return true;
				}
			}
			return false;
		}
		
		return false;
	}
	
	public static String analyseDegree(Degree myDegree, ArrayList<CourseRecord> myCRs, Catalog myCatalog)
	{
		String returnString = "";
		returnString += "Degree Name: " + myDegree.name + "\n";
		ArrayList<Section> mySections = myDegree.sections;
		for(Section presSection : mySections)
		{	
			//one tab
			returnString += "\tSection: " + presSection.identifier + " - ";
			returnString += presSection.name + "\n";
			
			returnString += getAnalysedSection(presSection, myCRs, myCatalog) + "\n";			
		}
		
		return returnString;
	}
	
	private static String getAnalysedSection(Section mySection, ArrayList<CourseRecord> myCRs, Catalog myCatalog)
	{
		String retString = "";
		Section.REQ_TYPE myType = mySection.getReqType();
		int numSubsections = mySection.numSubsections();
		
		if(myType.equals(Section.REQ_TYPE.Take_All))
		{
			retString += "\nPrint section take all\n";
			boolean outcome = true;
			for(int i = 1; i <= numSubsections; i++)
			{
				if(!examineSubsectionForCompletion(i, mySection.getReqTypeBySubsection(i), mySection, myCatalog, myCRs))
				{
					outcome = false;
				}
			}
			
			if(outcome == true)
			{
				retString += "\nSECTION COMPLETED!\n";
			}
			
			for(int i = 1; i <= numSubsections; i++)
			{
				retString += getAnalysedSubsection(i, mySection, myCRs, myCatalog) + "\n";
			}
		}
		else if(myType.equals(Section.REQ_TYPE.Take_Any))
		{
			retString += "\nPrint section take any\n";
			boolean outcome = false;
			for(int i = 1; i <= numSubsections; i++)
			{
				if(examineSubsectionForCompletion(i, mySection.getReqTypeBySubsection(i), mySection, myCatalog, myCRs))
				{
					outcome = true;
				}
			}
			
			if(outcome == true)
			{
				retString += "\nSECTION COMPLETED!\n";
			}
			
			for(int i = 1; i <= numSubsections; i++)
			{
				retString += getAnalysedSubsection(i, mySection, myCRs, myCatalog) + "\n";
			}
		}
		else if(myType.equals(Section.REQ_TYPE.Take_X_Courses))
		{
			retString += "\nPrint section take X courses\n";
			int count = 0;
			for(int i = 1; i <= numSubsections; i++)
			{
				if(examineSubsectionForCompletion(i, mySection.getReqTypeBySubsection(i), mySection, myCatalog, myCRs))
				{
					count++;
				}
			}
			
			if(count >= mySection.getUnitsNeeded())
			{
				retString += "\nSECTION COMPLETED!\n";
			}
			
			for(int i = 1; i <= numSubsections; i++)
			{
				retString += getAnalysedSubsection(i, mySection, myCRs, myCatalog) + "\n";
			}
		}
		else if(myType.equals(Section.REQ_TYPE.Take_X_Creds))
		{
			retString += "\nPrint section take x creds\n";
			if(examineSectionForCompletion(mySection, myCatalog, myCRs))
			{
				retString += "\nSECTION COMPLETED!\n";
			}
			else
			{
				int credCount = 0;
				for(String id : mySection.getAllCourses())
				{
					for(CourseRecord cr : myCRs)
					{
						if(cr.getCourseID().compareTo(id) == 0)
						{
							credCount += myCatalog.getCourse(id).getNumCreds();
						}
					}
				}
				
				retString += "\nCredits Needed: " + mySection.getUnitsNeeded() + " Credits Taken: " + credCount +"\n";
			}
			for(int i = 1; i <= numSubsections; i++)
			{
				retString += getAnalysedSubsection(i, mySection, myCRs, myCatalog) + "\n";
			}
		}
		else if(myType.equals(Section.REQ_TYPE.XOR))
		{
			retString += "\nPrint section take xor\n";
			boolean outcome = false;
			for(int i = 1; i <= numSubsections; i++)
			{
				if(examineSubsectionForCompletion(i, mySection.getReqTypeBySubsection(i), mySection, myCatalog, myCRs))
				{
					outcome = true;
				}
			}
			
			if(outcome == true)
			{
				retString += "\nSECTION COMPLETED!\n";
			}
			
			for(int i = 1; i <= numSubsections; i++)
			{
				retString += getAnalysedSubsection(i, mySection, myCRs, myCatalog) + "\n";
			}
		}
		else 
		{
			retString += "YA DONE GOOFED\n";
		}
		
		return retString;
	}
	
	private static String getAnalysedSubsection(int subsectionIdentifier, Section mySection, ArrayList<CourseRecord> myCRs, Catalog myCatalog)
	{
		String retString = "";
		Section.REQ_TYPE myType = mySection.getReqTypeBySubsection(subsectionIdentifier);
		String[][] serieses = mySection.getCoursesInSubsection(subsectionIdentifier);
		
		if(false)
		{/*
			System.out.println("Printing serieses");
			for(String[] series : serieses)
			{
				String out = "Series: ";
				for(String id : series)
				{
					out += id + " ";
				}
				System.out.println(out);
				
			}*/
		}
		
		if(myType == Section.REQ_TYPE.Take_All)
		{
			String[] series = serieses[0];
			if(examineSeriesForCompletingXCourses(series, myCRs, series.length) == true)
			{
				retString += "Courses Taken:\n";
				for(String id : series)
				{
					retString += id+"\n";
				}
			}
			else
			{
				retString += "Courses Taken:\n";
				ArrayList<String> notTaken = new ArrayList<String>();
				for(String id : series)
				{
					boolean added = false;
					for(CourseRecord cr : myCRs)
					{
						
						if(cr.getCourseID().compareTo(id) == 0)
						{
							retString += id + "\n";
							added = true;
						}
						
					}
					if(!added)
					{
						notTaken.add(id);
					}
				}
				retString += "Courses Not Taken:\n";
				for(String id : notTaken)
				{
					retString += id + "\n";
				}
			}
		}
		else if(myType == Section.REQ_TYPE.Take_Any || myType == Section.REQ_TYPE.XOR)
		{
			String tempString = "";
			for(int i = 0; i != serieses.length; i++)
			{
				String[] series = serieses[i];
				if(examineSeriesForCompletingXCourses(series, myCRs, series.length) == true)
				{
					retString += "Courses Taken:\n";
					for(String id : series)
					{
						retString += id+"\n";
					}
				}
				else
				{
					tempString += "Courses Taken:\n";
					ArrayList<String> notTaken = new ArrayList<String>();
					for(String id : series)
					{
						boolean added = false;
						for(CourseRecord cr: myCRs)
						{
							if(cr.getCourseID().equals(id))
							{
								tempString += id + "\n";
								added = true;
							}
						}
						if(!added)
						{
							notTaken.add(id);
						}
					}
					tempString += "Courses Not Taken:\n";
					for(String id : notTaken)
					{
						tempString += id + "\n";
					}
				}
			}
			retString += tempString;	
		}
		else if(myType == Section.REQ_TYPE.Take_X_Courses)
		{
			int x = mySection.getUnitsNeeded();
			ArrayList<String> taken = new ArrayList<String>();
			ArrayList<String> notTaken = new ArrayList<String>();
			for(int i = 0; i != serieses.length; i++)
			{
				String[] series = serieses[i];
				
				for(String id : series)
				{
					boolean added = false;
					for(CourseRecord cr : myCRs)
					{
						if(myCRs.contains(id))
						{
							taken.add(id);
							added = true;
						}
					}
					if(!added)
					{
						notTaken.add(id);
					}
					
				}
				
			}
			if(taken.size() >= x)
			{
				retString += "CoursesTaken:\n";
				for(String id : taken)
				{
					retString += id + "\n";
				}
			}
			else
			{
				retString += "CoursesTaken:\n";
				for(String id : taken)
				{
					retString += id + "\n";
				}
				retString += "Courses Not Taken:\n";
				for(String id : notTaken)
				{
					retString += id + "\n";
				}
			}
		}
		else if(myType == Section.REQ_TYPE.Take_X_Creds)
		{
			int x = mySection.getUnitsNeeded();
			ArrayList<String> taken = new ArrayList<String>();
			ArrayList<String> notTaken = new ArrayList<String>();
			for(int i = 0; i != serieses.length; i++)
			{
				String[] series = serieses[i];
				
				for(String id : series)
				{
					boolean added = false;
					for(CourseRecord cr : myCRs)
					{
						if(cr.getCourseID().equals(id))
						{
							taken.add(id);
							added = true;
						}
					}
					if(!added)
					{
						notTaken.add(id);
					}
				}
			}
			
			int credCount = 0;
			for(String id : taken)
			{
				credCount += myCatalog.getCourse(id).getNumCreds();
			}
			
			if(credCount >= x)
			{
				retString += "Credits Taken: " + credCount + "\nCoursesTaken:\n";
				for(String id : taken)
				{
					retString += id + "\n";
				}
			}
			else
			{
				retString += "Take " + x + " Credits\nCredits Taken: " + credCount + "\nCoursesTaken:\n";
				for(String id : taken)
				{
					retString += id + "\n";
				}
				retString += "Courses Not Taken:\n";
				for(String id : notTaken)
				{
					retString += id + "\n";
				}
			}
		}
		///else if(myType == Section.REQ_TYPE.XOR)
		//{
			
		//}
		else 
		{
			retString += "YA DONE GOOFED\nERROR IN DEGREE AUDIT";
		}
		
		return retString;
		
	}
	
	private static boolean examineSubsectionForCompletion(int subSectionIdentifier, Section.REQ_TYPE myType, Section mySection, Catalog catalog, ArrayList<CourseRecord> myCRs)
	{	
		String[][] serieses = mySection.getCoursesInSubsection(subSectionIdentifier);
		
		//start here
		if(myType == Section.REQ_TYPE.Take_All)
		{
			ArrayList<String> ids = new ArrayList<String>();
			String[] series = serieses[0];
			for(String courseID : series)
			{
				for(CourseRecord cr : myCRs)
				{
					if(cr.getCourseID().compareTo(courseID) == 0)
					{
						ids.add(courseID);
					}
				}
				if(ids.size() != series.length)
				{
					return false;
				}
			}
			
			return true;
		}
		else if(myType == Section.REQ_TYPE.Take_Any)
		{
			for(String[] series : serieses)
			{
				int count = 0;
				for(String courseID : series)
				{
					for(CourseRecord cr : myCRs)
					{
						if(cr.getCourseID().compareTo(courseID) != 0)
						{
							count++;
						}
					}
				}
				if(count == series.length)
				{
					return true;
				}
			}
			return false;
		}
		else if(myType == Section.REQ_TYPE.Take_X_Courses)
		{
			for(String[] series : serieses)
			{
				int count = 0;
				for(String courseID : series)
				{
					for(CourseRecord cr : myCRs)
					{
						if(cr.getCourseID().compareTo(courseID) != 0)
						{
							count++;
						}
					}
				}
				if(count == mySection.getUnitsNeededBySubsection(subSectionIdentifier))
				{
					return true;
				}
			}
			return false;
		}
		else if(myType == Section.REQ_TYPE.Take_X_Creds)
		{
			for(String[] series : serieses)
			{
				int count = 0;
				for(String courseID : series)
				{
					for(CourseRecord cr : myCRs)
					{
						if(cr.getCourseID().compareTo(courseID) != 0)
						{
							count += catalog.getCourse(courseID).getNumCreds();
						}
					}
				}
				if(count == mySection.getUnitsNeededBySubsection(subSectionIdentifier))
				{
					return true;
				}
			}
			return false;
		}
		else if(myType == Section.REQ_TYPE.XOR)
		{
			for(String[] series : serieses)
			{
				int count = 0;
				for(String courseID : series)
				{
					for(CourseRecord cr : myCRs)
					{
						if(cr.getCourseID().compareTo(courseID) != 0)
						{
							count++;
						}
					}
				}
				if(count == series.length)
				{
					return true;
				}
			}
			return false;
		}
		else
		{
			return false;
		}
		
		
	}
	
	private static boolean examineSeriesForCompletingXCourses(String[] ids, ArrayList<CourseRecord> myCRs, int numCourses)
	{
		ArrayList<String> myIDs = examineSeriesForCompletion(ids, myCRs);
		
		//System.out.println("\n\nPRINTING IDS");
		//for(String id: ids)
		//{
		//	System.out.println(id);
		//}
		//System.out.println("\n\nPRINTING COMPLETED");
		//for(CourseRecord cr: myCRs)
		//{
		//	String id = cr.getCourseID();
		//	System.out.println(id);
		//}
		
		
		if(myIDs.size() >= numCourses)
		{
			return true;
		}
		return false;
	}
	
	private static boolean examineSeriesForCompletingXCredits(String[] ids, ArrayList<CourseRecord> myCRs, Catalog catalog, int numCredits)
	{
		ArrayList<String> myIDs = examineSeriesForCompletion(ids, myCRs);
		double creds = 0;
		for(String id : myIDs)
		{
			creds += catalog.getCourse(id).getNumCreds();
		}
		
		if(creds >= numCredits)
		{
			return true;
		}
		return false;
	}
	
	private static ArrayList<String> examineSeriesForCompletion(String[] ids, ArrayList<CourseRecord> myCRs)
	{
		ArrayList<String> completed = new ArrayList<String>();
		for(String id : ids)
		{
			for(CourseRecord cr : myCRs)
			{
				if (cr.getCourseID().compareTo(id) == 0)
				{
					completed.add(id);
				}
			}
		}
		return completed;
	}
}
